home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 July: Mac OS SDK / Dev.CD Jul 97 SDK2.toast / Development Kits (Disc 2) / QuickTake Digital Camera / MyQuickTakeApp 1.0.1TC7 ƒ / Sources / QuickTakePICT.c < prev   
Encoding:
C/C++ Source or Header  |  1995-05-30  |  46.4 KB  |  1,597 lines  |  [TEXT/MMCC]

  1. /*
  2.     File:        QuickTakePICT.c
  3.     
  4.     Contains:    My Application Shell.
  5.  
  6.     Written by:    John Wang
  7.  
  8.     Copyright:    © 1994 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.         <1>        4/13/94        WJA        First release.  MakeQuickTakePicture call originally written
  13.                                     by Wayman Askey as a sample to generate a Venus picture.
  14.         <4>        09/30/94    JW        Updated to follow the "QuickTake File Format
  15.                                     Specifications for Venus/Nimbus" to the letter.
  16.  
  17.     To Do:
  18.     
  19. */
  20.  
  21. #include    "MoreFilesExtras.h"
  22. #include    "CmDriver.h"
  23.  
  24. #include    "QuickTakePICT.h"
  25.  
  26. //    Globals needed for QuickDraw bottleneck procs.
  27. ImageHeader    gImageHeader;
  28. Ptr            gImageBuffer;
  29.  
  30. /* ------------------------------------------------------------------------- */
  31.  
  32. /*
  33.     Description:    MakeQuickTakePicture()
  34.  
  35.     Format Params:    
  36.         Name            Usage    Description/Assumptions
  37.         ----            ----    -----------------------
  38.         imageHeader        PI        This contains the header to the compressed data.
  39.         imageBuffer        PI        This contains the compressed data.
  40.         colorMatrix        PI        Nil if not used.
  41.         decompTable        PI        Nil if not used.
  42.         picture            PO        A picture is created and returned.  The handle is unlocked.
  43.                                 
  44.     Usage: P=Parameter,R=ReturnValue,E=External,G=FileGlobal,L=Local,I=Input,O=Output
  45.     
  46.     Error Handling:    If noErr is returned, you can assume a valid pict file has been returned.
  47.  
  48.     Special Notes:    xxx put other comments here xxx
  49.  
  50. */
  51.  
  52. OSErr InitializeImageData(ImageHeader *imageHeader, Ptr imageBuffer,
  53.         CmColorMatrixPtr colorMatrix, BufferPtr decompTable, Ptr *imageData);
  54. OSErr InitializeImageDescription(ImageHeader *imageHeader, ImageDescriptionHandle *imageDesc, Size dataSize);
  55.  
  56. OSErr InitializeImageData(ImageHeader *imageHeader, Ptr imageBuffer,
  57.         CmColorMatrixPtr colorMatrix, BufferPtr decompTable, Ptr *imageData)
  58. {
  59.     OSErr            err;
  60.     short            headerSize;
  61.     Size            decompSize;
  62.     
  63.     //    Initialize.
  64.     err = noErr;
  65.     
  66.     //    Check and initialize parameters.
  67.     if ( imageData == nil ) {
  68.         err = paramErr;
  69.         goto bail;
  70.     }
  71.     *imageData = nil;
  72.     if ( imageBuffer == nil ) {
  73.         err = paramErr;
  74.         goto bail;
  75.     }
  76.     if ( imageHeader == nil ) {
  77.         err = paramErr;
  78.         goto bail;
  79.     }
  80.     
  81.     //    Get decompTable size.  This size should be for QT 100 or QT 150
  82.     if ( decompTable != nil ) {
  83.         decompSize = GetPtrSize((Ptr) decompTable);
  84.         if ( decompSize != kCmDecompTableSize100 && decompSize != kCmDecompTableSize150 ) {
  85.             err = paramErr;
  86.             goto bail;
  87.         }
  88.     } else
  89.         decompSize = 0;
  90.     
  91.     //    Set headersize.
  92.     if ( colorMatrix == nil ) {
  93.         if ( decompTable == nil ) {
  94.             headerSize = sizeof(ImageHeader);
  95.         } else if ( decompTable != nil && decompSize == kCmDecompTableSize100 ) {
  96.             headerSize = sizeof(ImageHeader_CT100);
  97.         } else if ( decompTable != nil && decompSize == kCmDecompTableSize150 ) {
  98.             headerSize = sizeof(ImageHeader_CT150);
  99.         } else {
  100.             err = paramErr;
  101.             goto bail;
  102.         }
  103.     } else {
  104.         if ( decompTable == nil ) {
  105.             headerSize = sizeof(ImageHeader_CM);
  106.         } else if ( decompTable != nil && decompSize == kCmDecompTableSize100 ) {
  107.             headerSize = sizeof(ImageHeader_CM_CT100);
  108.         } else if ( decompTable != nil && decompSize == kCmDecompTableSize150 ) {
  109.             headerSize = sizeof(ImageHeader_CM_CT150);
  110.         } else {
  111.             err = paramErr;
  112.             goto bail;
  113.         }
  114.     }
  115.     
  116.     //    Check for valid signature and version.
  117.     if ( ((imageHeader->signature == 'qktk') && (imageHeader->version == 1)) ||
  118.         ((imageHeader->signature == 'qktn') && (imageHeader->version == 2)) ) {
  119.         
  120.         //    Create new memory block depending on what's supposed to be in it.
  121.         *imageData = NewPtr((imageHeader->dataSize + headerSize));
  122.         
  123.         //    If we succeed...
  124.         if (*imageData != nil) {
  125.             //    Append the QuickTake image header to the raw compressed image.
  126.             if ( colorMatrix == nil ) {
  127.                 if ( decompTable == nil ) {
  128.                     BlockMove((Ptr) imageHeader, *imageData, headerSize);
  129.                 } else if ( decompTable != nil && decompSize == kCmDecompTableSize100 ) {
  130.                     ImageHeader_CT100    imageHeader_CT100;
  131.                     imageHeader_CT100.signature = imageHeader->signature;
  132.                     imageHeader_CT100.version = imageHeader->version;
  133.                     imageHeader_CT100.flags = imageHeader->flags | kQktkHasCompressionTable;
  134.                     imageHeader_CT100.compTableSize = kCmDecompTableSize100;
  135.                     imageHeader_CT100.dataSize = imageHeader->dataSize;
  136.                     BlockMove(decompTable, imageHeader_CT100.compTable, kCmDecompTableSize100);
  137.                     BlockMove((Ptr) &imageHeader_CT100, *imageData, headerSize);
  138.                 } else if ( decompTable != nil && decompSize == kCmDecompTableSize150 ) {
  139.                     ImageHeader_CT150    imageHeader_CT150;
  140.                     imageHeader_CT150.signature = imageHeader->signature;
  141.                     imageHeader_CT150.version = imageHeader->version;
  142.                     imageHeader_CT150.flags = imageHeader->flags | kQktkHasCompressionTable;
  143.                     imageHeader_CT150.compTableSize = kCmDecompTableSize150;
  144.                     imageHeader_CT150.dataSize = imageHeader->dataSize;
  145.                     BlockMove(decompTable, imageHeader_CT150.compTable, kCmDecompTableSize150);
  146.                     BlockMove((Ptr) &imageHeader_CT150, *imageData, headerSize);
  147.                 }
  148.             } else {
  149.                 if ( decompTable == nil ) {
  150.                     ImageHeader_CM    imageHeader_CM;
  151.                     imageHeader_CM.signature = imageHeader->signature;
  152.                     imageHeader_CM.version = imageHeader->version;
  153.                     imageHeader_CM.flags = imageHeader->flags | kQktkHasColorMatrix;
  154.                     imageHeader_CM.dataSize = imageHeader->dataSize;
  155.                     BlockMove(&(colorMatrix->colorCorrectionMatrix), imageHeader_CM.colorMatrix, sizeof(double[12]));
  156.                     BlockMove((Ptr) &imageHeader_CM, *imageData, headerSize);
  157.                 } else if ( decompTable != nil && decompSize == kCmDecompTableSize100 ) {
  158.                     ImageHeader_CM_CT100    imageHeader_CM_CT100;
  159.                     imageHeader_CM_CT100.signature = imageHeader->signature;
  160.                     imageHeader_CM_CT100.version = imageHeader->version;
  161.                     imageHeader_CM_CT100.flags = imageHeader->flags | kQktkHasColorMatrix | kQktkHasCompressionTable;
  162.                     imageHeader_CM_CT100.compTableSize = kCmDecompTableSize100;
  163.                     imageHeader_CM_CT100.dataSize = imageHeader->dataSize;
  164.                     BlockMove(&(colorMatrix->colorCorrectionMatrix), imageHeader_CM_CT100.colorMatrix, sizeof(double[12]));
  165.                     BlockMove(decompTable, imageHeader_CM_CT100.compTable, kCmDecompTableSize100);
  166.                     BlockMove((Ptr) &imageHeader_CM_CT100, *imageData, headerSize);
  167.                 } else if ( decompTable != nil && decompSize == kCmDecompTableSize150 ) {
  168.                     ImageHeader_CM_CT150    imageHeader_CM_CT150;
  169.                     imageHeader_CM_CT150.signature = imageHeader->signature;
  170.                     imageHeader_CM_CT150.version = imageHeader->version;
  171.                     imageHeader_CM_CT150.flags = imageHeader->flags | kQktkHasColorMatrix | kQktkHasCompressionTable;
  172.                     imageHeader_CM_CT150.compTableSize = kCmDecompTableSize150;
  173.                     imageHeader_CM_CT150.dataSize = imageHeader->dataSize;
  174.                     BlockMove(&(colorMatrix->colorCorrectionMatrix), imageHeader_CM_CT150.colorMatrix, sizeof(double[12]));
  175.                     BlockMove(decompTable, imageHeader_CM_CT150.compTable, kCmDecompTableSize150);
  176.                     BlockMove((Ptr) &imageHeader_CM_CT150, *imageData, headerSize);
  177.                 }
  178.             }
  179.             BlockMove(imageBuffer, (*imageData + headerSize), imageHeader->dataSize);
  180.         } else {
  181.             err = memFullErr;
  182.             goto bail;
  183.         }
  184.     } else {
  185.         err = paramErr;
  186.         goto bail;
  187.     }
  188.  
  189. bail:
  190.     return (err);
  191. }
  192.  
  193. OSErr InitializeImageDescription(ImageHeader *imageHeader, ImageDescriptionHandle *imageDesc, Size dataSize)
  194. {
  195.     OSErr            err;
  196.     Fixed            resolution;
  197.     short            w, h;
  198.  
  199.     //    Initialize.
  200.     err = noErr;
  201.     
  202.     //    Check and intialize parameters.
  203.     if ( imageDesc == nil ) {
  204.         err = paramErr;
  205.         goto bail;
  206.     }
  207.     *imageDesc = nil;
  208.     if ( imageHeader == nil ) {
  209.         err = paramErr;
  210.         goto bail;
  211.     }
  212.     
  213.     //    Check for valid signature and version.
  214.     if ( (imageHeader->signature == 'qktk') && (imageHeader->version == 1) ) {
  215.         if (imageHeader->flags & kQktkHiResImage) {
  216.             resolution = Long2Fix(72L);
  217.             w = 640;
  218.             h = 480;
  219.         } else if (imageHeader->flags & kQktkStdResImage) {
  220.             resolution = Long2Fix(72L);
  221.             w = 320;
  222.             h = 240;
  223.         } else if (imageHeader->flags & kQktkThumbnailImage) {
  224.             resolution = Long2Fix(72L);
  225.             w = 80;
  226.             h = 60;
  227.         } else {
  228.             err = paramErr;
  229.             goto bail;
  230.         }
  231.     } else if ( (imageHeader->signature == 'qktn') && (imageHeader->version == 2) ) {
  232.         if (imageHeader->flags & kQktkHiResImage) {
  233.             resolution = Long2Fix(72L);
  234.             w = 640;
  235.             h = 480;
  236.         } else if (imageHeader->flags & kQktkStdResImage) {
  237.             resolution = Long2Fix(72L);
  238.             w = 640;
  239.             h = 480;
  240.         } else if (imageHeader->flags & kQktkThumbnailImage) {
  241.             resolution = Long2Fix(72L);
  242.             w = 80;
  243.             h = 60;
  244.         } else {
  245.             err = paramErr;
  246.             goto bail;
  247.         }
  248.     } else {
  249.         err = paramErr;
  250.         goto bail;
  251.     }
  252.     
  253.     //    Ok, now let's create the imageDesc.
  254.     *imageDesc = (ImageDescriptionHandle) NewHandleClear(sizeof(ImageDescription));
  255.     if ( *imageDesc == nil ) {
  256.         err = memFullErr;
  257.         goto bail;
  258.     }
  259.     MoveHHi((Handle) *imageDesc);
  260.     HLock((Handle) *imageDesc);
  261.     
  262.     //    Fill out the image description.  Refer to the Image Compression
  263.     //    Manager chapter of "Inside Macintosh: QuickTime" for a compete
  264.     //    description of this data structure.
  265.     (**imageDesc)->idSize = sizeof(ImageDescription);
  266.     (**imageDesc)->cType = (CodecType) imageHeader->signature;
  267.     (**imageDesc)->version = 0;
  268.     (**imageDesc)->revisionLevel = 0;
  269.     (**imageDesc)->vendor = 0;
  270.     (**imageDesc)->temporalQuality = 0;
  271.     (**imageDesc)->spatialQuality = codecNormalQuality;
  272.     (**imageDesc)->hRes = (**imageDesc)->vRes = resolution;
  273.     (**imageDesc)->dataSize = dataSize;
  274.     BlockMove((Ptr)"\pQuickTake™", (Ptr)(**imageDesc)->name, 11);
  275.     (**imageDesc)->depth = 24;
  276.     (**imageDesc)->clutID = -1;
  277.     
  278.     //    Determine whether image should be displayed as a vertical (width < height)
  279.     //    or horizontal (width > height) image.
  280.     if (imageHeader->flags & kQktkVerticalImage) {
  281.         (**imageDesc)->width = h;
  282.         (**imageDesc)->height = w;
  283.     } else {
  284.         (**imageDesc)->width = w;
  285.         (**imageDesc)->height = h;
  286.     }
  287.  
  288. bail:    
  289.     return (err);
  290. }
  291.  
  292. OSErr MakeQuickTakePicture(ImageHeader *imageHeader, Ptr imageBuffer,
  293.         CmColorMatrixPtr colorMatrix, BufferPtr decompTable, PicHandle *pict)
  294. {
  295.     OSErr                    err;
  296.     ImageDescriptionHandle    imageDesc;
  297.     Ptr                        imageData;
  298.     Rect                    bounds;
  299.     CGrafPtr                saveport;
  300.     GDHandle                savegdevice;
  301.     GWorldPtr                myGWorld;
  302.     OpenCPicParams            myPicParams;
  303.     Rect                    boundsRect = {0, 0, 8, 8};
  304.     
  305.     //    Things that we must initialize first.
  306.     GetGWorld(&saveport, &savegdevice);
  307.     myGWorld = nil;
  308.     imageDesc = nil;
  309.     imageData = nil;
  310.     
  311.     if ( pict == nil ) {
  312.         err = paramErr;
  313.         goto bail;
  314.     }
  315.     *pict = nil;
  316.     if ( imageBuffer == nil ) {
  317.         err = paramErr;
  318.         goto bail;
  319.     }
  320.     if ( imageHeader == nil ) {
  321.         err = paramErr;
  322.         goto bail;
  323.     }
  324.     
  325.     //    Rather than depend on a graphics port, we create an offscreen gworld to use as the current
  326.     //    port and gdevice for creating the picture.
  327.     err = NewGWorld(&myGWorld, 32, &boundsRect, nil, nil, 0);
  328.     if ( err != noErr ) {
  329.         myGWorld = nil;
  330.         goto bail;
  331.     }
  332.     if ( myGWorld == nil ) {
  333.         err = memFullErr;
  334.         myGWorld = nil;
  335.         goto bail;
  336.     }
  337.     SetGWorld(myGWorld, nil);
  338.     
  339.     //    If the gworld was created properly, then create imageData.
  340.     err = InitializeImageData(imageHeader, imageBuffer, colorMatrix, decompTable, &imageData);
  341.     if ( err != noErr ) {
  342.         goto bail;
  343.     }
  344.         
  345.     //    If the gworld was created properly, then create imageDesc.
  346.     err = InitializeImageDescription(imageHeader, &imageDesc, GetPtrSize(imageData));
  347.     if ( err != noErr ) {
  348.         goto bail;
  349.     }
  350.         
  351.     //    Create the picture.
  352.     SetRect(&bounds, 0, 0, (**imageDesc).width, (**imageDesc).height);
  353.     myPicParams.srcRect = bounds;
  354.     myPicParams.hRes = (**imageDesc).hRes;
  355.     myPicParams.vRes = (**imageDesc).vRes;
  356.     
  357.     //    Special case for hi-res Venus pictures...
  358.     if ( (imageHeader->signature == 'qktk') && (imageHeader->version == 1) ) {
  359.         if (imageHeader->flags & kQktkHiResImage) {
  360.             myPicParams.hRes = (**imageDesc).hRes << 1;
  361.             myPicParams.vRes = (**imageDesc).vRes << 1;
  362.         }
  363.     //    Special case for Nimbus pictures...
  364.     } else if ( (imageHeader->signature == 'qktn') && (imageHeader->version == 2) ) {
  365.         if (imageHeader->flags & kQktkHiResImage) {
  366.             myPicParams.hRes = (**imageDesc).hRes << 1;
  367.             myPicParams.vRes = (**imageDesc).vRes << 1;
  368.         } else if (imageHeader->flags & kQktkStdResImage) {
  369.             myPicParams.hRes = (**imageDesc).hRes << 1;
  370.             myPicParams.vRes = (**imageDesc).vRes << 1;
  371.         }
  372.     }
  373.     
  374.     myPicParams.version = -2;
  375.     myPicParams.reserved1 = 0;
  376.     myPicParams.reserved2 = 0;
  377.     *pict = OpenCPicture(&myPicParams);
  378.     err = FDecompressImage(imageData, imageDesc, myGWorld->portPixMap, (Rect *)nil,
  379.         (MatrixRecordPtr)nil, ditherCopy, (RgnHandle)nil, (PixMapHandle)nil, (Rect *)nil,
  380.         codecHighQuality, anyCodec, 0L, nil, nil);
  381.     ClosePicture();
  382.     
  383.     //    Check for failure.
  384.     if ( (err != noErr) || (GetHandleSize((Handle)*pict) == sizeof(Picture)) ) {
  385.         err = (err == noErr) ? -1 : err;
  386.         if ( *pict != nil )
  387.             KillPicture(*pict);
  388.         *pict = nil;
  389.         goto bail;
  390.     }
  391.     
  392.     //    We will make sure the picture is unlocked now that we succeeded.
  393.     HUnlock((Handle) *pict);
  394.  
  395. bail:
  396.     SetGWorld(saveport, savegdevice);
  397.  
  398.     if ( myGWorld != nil )
  399.         DisposeGWorld(myGWorld);
  400.     if ( imageDesc != nil )
  401.         DisposeHandle((Handle) imageDesc);
  402.     if ( imageData != nil )
  403.         DisposePtr(imageData);
  404.         
  405.     return (err);
  406. }
  407.  
  408. /* ------------------------------------------------------------------------- */
  409.  
  410. /*
  411.     Description:    LoadThumbnailPict()
  412.                     Given a FSSpec, read in the file and try to get a thumbnail pict.
  413.                     If it is a QuickTake file, then the thumbnail is used.  Otherwise, the
  414.                     thumbnail is created using the full pict.  The size of the pict returned
  415.                     canbe any size.  So, don't assume that it is thumbnail size.
  416.  
  417.     Format Params:    
  418.         Name            Usage    Description/Assumptions
  419.         ----            ----    -----------------------
  420.         theFSSpec        PI        Pass in a valid FSSpec to load the picture from.
  421.         pict            PO        if pict is not nil, then valid PicHandle will be returned.
  422.                                 The pict will be an unlocked handle.
  423.                                 
  424.     Usage: P=Parameter,R=ReturnValue,E=External,G=FileGlobal,L=Local,I=Input,O=Output
  425.     
  426.     Error Handling:    If noErr is returned, you can assume a valid pict.
  427.  
  428.     Special Notes:    Future Optional upgrade: use the pnot preview pict if available.
  429.  
  430. */
  431.  
  432. OSErr LoadThumbnailPict(FSSpec *theFSSpec, PicHandle *pict)
  433. {
  434.     OSErr                    err;
  435.     short                    myRefNum;
  436.     long                    thumbnailOffset;
  437.     long                    fileSize;
  438.     
  439.     //    Initialize variables used in this function.
  440.     myRefNum = -1;
  441.     err = noErr;
  442.  
  443.     //    Check parameters after initialization.
  444.     if ( pict == nil ) {
  445.         err = paramErr;
  446.         goto bail;
  447.     }
  448.     *pict = nil;
  449.     if ( theFSSpec == nil ) {
  450.         err = paramErr;
  451.         goto bail;
  452.     }
  453.     
  454.     //    Try data fork first.  The data fork must be greater than 512 in size...
  455.     err = FSpOpenDF(theFSSpec, fsRdPerm, &myRefNum);
  456.     if ( err != noErr ) {
  457.         myRefNum = -1;
  458.         err = noErr;    //    Remove err and try resource fork.
  459.         goto tryResourceFork;
  460.     }
  461.     err = GetEOF(myRefNum, &fileSize);
  462.     if ( err != noErr ) {
  463.         err = noErr;    //    Remove err and try resource fork.
  464.         goto tryResourceFork;
  465.     }
  466.     if ( fileSize > 512 ) {
  467.         long            headerSize, pictSize, origPictSize;
  468.         unsigned char    header[512];
  469.         
  470.         //    Read in fileHeader first.
  471.         headerSize = 512;
  472.         err = FSRead(myRefNum, &headerSize, header);
  473.         if ( err != noErr )
  474.             goto bail;
  475.         if ( headerSize != 512 ) {
  476.             err = ioErr;
  477.             goto bail;
  478.         }
  479.         
  480.         //    If it is a valid Venus or Nimbus file header, then we will use thumbnailOffset from
  481.         //    header.  We will also read in the CmPictureInfo in this case.  Otherwise, don't since
  482.         //    we can't be sure of the file version and structure.
  483.         //    We check the version to make sure it is 0 since that is the file format version
  484.         //    as defined in the "QuickTake File Format Specification for Venus/Nimbus".
  485.         if ( (((PictFileHeader *) header)->signature == 'qktk' &&
  486.                     ((PictFileHeader *) header)->version == 0) ||
  487.                 (((PictFileHeader *) header)->signature == 'qktn' &&
  488.                     ((PictFileHeader *) header)->version == 0) ) {
  489.             thumbnailOffset = ((PictFileHeader *) header)->thumbnailOffset;
  490.         } else
  491.             thumbnailOffset = 0;
  492.         
  493.         //    Read in pict.  If the thumbnail exists, then read upto the thumbnail.  Otherwise,
  494.         //    assume that the entire rest of file is part of picture.
  495.         if ( thumbnailOffset > 0 )
  496.             pictSize = thumbnailOffset - 512;
  497.         else
  498.             pictSize = fileSize - 512;
  499.         origPictSize = pictSize;
  500.         
  501.         //    Use pict if thumbnail doesn't exist.
  502.         if ( thumbnailOffset == 0 ){
  503.             *pict = (PicHandle) NewHandle(pictSize);
  504.             if ( *pict == nil ) {
  505.                 err = memFullErr;
  506.                 goto bail;
  507.             }
  508.             MoveHHi((Handle) *pict);
  509.             HLock((Handle) *pict);
  510.             err = FSRead(myRefNum, &pictSize, **pict);
  511.             if ( err != noErr )
  512.                 goto bail;
  513.             if ( pictSize != origPictSize ) {
  514.                 err = ioErr;
  515.                 goto bail;
  516.             }
  517.             HUnlock((Handle) *pict);
  518.         //    Skip pict if thumbnail exists.
  519.         } else {
  520.             //    Simply advance the file position otherwise.
  521.             err = SetFPos(myRefNum, fsFromMark, pictSize);
  522.             if ( err != noErr )
  523.                 goto bail;
  524.         }
  525.         
  526.         //    If there is a thumbnail, then continue.
  527.         if ( thumbnailOffset != 0 ) {
  528.             long                    readSize, origReadSize;
  529.             ThumbnailHeader            tempThumbnailHeader;
  530.             Handle                    thumbnail;
  531.             
  532.             //    Read in thumbnail header into tempThumbnailHeader.
  533.             readSize = sizeof(ThumbnailHeader);
  534.             origReadSize = readSize;
  535.             err = FSRead(myRefNum, &readSize, &tempThumbnailHeader);
  536.             if ( err != noErr )
  537.                 goto bail;
  538.             if ( readSize != origReadSize)  {
  539.                 err = ioErr;
  540.                 goto bail;
  541.             }
  542.         
  543.             //    Now read in thumbnail.
  544.             readSize = tempThumbnailHeader.dataSize;
  545.             origReadSize = readSize;
  546.             thumbnail = NewHandle(readSize);
  547.             if ( thumbnail == nil ) {
  548.                 err = memFullErr;
  549.                 goto bail;
  550.             }
  551.             MoveHHi(thumbnail);
  552.             HLock(thumbnail);
  553.             err = FSRead(myRefNum, &readSize, *thumbnail);
  554.             if ( err != noErr ) {
  555.                 DisposeHandle(thumbnail);
  556.                 goto bail;
  557.             }
  558.             if ( readSize != origReadSize ) {
  559.                 DisposeHandle(thumbnail);
  560.                 err = ioErr;
  561.                 goto bail;
  562.             }
  563.                 
  564.             //    Make a pict out of it.
  565.             err = MakeQuickTakePicture((ImageHeader *) &tempThumbnailHeader, *thumbnail, nil, nil, pict);
  566.             if ( err != noErr ) {
  567.                 DisposeHandle(thumbnail);
  568.                 goto bail;
  569.             }
  570.  
  571.             HUnlock(thumbnail);
  572.             DisposeHandle((Handle) thumbnail);
  573.         }
  574.     }
  575.  
  576.     //    Try resource fork if we still haven't loaded a picture.
  577. tryResourceFork:
  578.     //    Close data fork first.
  579.     if ( myRefNum != -1 ) {
  580.         FSClose(myRefNum);
  581.         myRefNum = -1;
  582.     }
  583.     if ( *pict == nil ) {
  584.         short    resFile;
  585.         resFile = FSpOpenResFile(theFSSpec, fsRdPerm);
  586.         if ( resFile == -1 ) {
  587.             err = ioErr;
  588.             goto bail;
  589.         }
  590.         *pict = (PicHandle) Get1IndResource('PICT', 1);
  591.         if ( *pict != nil ) {
  592.             DetachResource((Handle) *pict);
  593.             HUnlock((Handle) *pict);
  594.         }
  595.         CloseResFile(resFile);
  596.     }
  597.     
  598. bail:
  599.     //    Close data fork if still opened.
  600.     if ( myRefNum != -1 )
  601.         FSClose(myRefNum);
  602.     
  603.     //    Dispose if error occured.
  604.     if ( err != noErr ) {
  605.         if ( pict != nil ) {
  606.             if ( *pict != nil ) {
  607.                 DisposeHandle((Handle) *pict);
  608.                 *pict = nil;
  609.             }
  610.         }
  611.     }
  612.     return ( noErr );
  613. }
  614.  
  615. /* ------------------------------------------------------------------------- */
  616.  
  617. /*
  618.     Description:    LoadPict()
  619.                     Given a FSSpec, read in the file and try to get a pict, thumbnail,
  620.                     thumnailHeader, and pictureInfo.  If you don't want the pict, thumbnail, thumbnailHeader,
  621.                     or pictureInfo you can pass in nil.  (i.e.   You can request any combination of pict
  622.                     thumbnail, or thumbnailHeader.  In fact, you can request the thumbnail
  623.                     without requesting the thumbnailHeader or vice-versa.  If there is no thumbnail,
  624.                     a nil handle is returned and the thumbnailHeader will contain all 0s.)
  625.  
  626.     Format Params:    
  627.         Name            Usage    Description/Assumptions
  628.         ----            ----    -----------------------
  629.         theFSSpec        PI        Pass in a valid FSSpec to load the picture from.
  630.         pict            PO        if pict is not nil, then valid PicHandle will be returned.
  631.                                 The pict will be an unlocked handle.
  632.         thumbnail        PO        If thumbnail is not nil, then a thumbnail will be returned if
  633.                                 it exists.  The thumbnail will be an unlocked handle.
  634.         thumbnailHeader    PO        If thumbnailHeader is not nil, then a thumbnailHeader will be returned if
  635.                                 it exists.
  636.         pictureInfo        PO        if pictureInfo is not nil, then it will be returned.  If there is no
  637.                                 pictureInfo in the file, a zeroed out structure is returned.
  638.                                 
  639.     Usage: P=Parameter,R=ReturnValue,E=External,G=FileGlobal,L=Local,I=Input,O=Output
  640.     
  641.     Error Handling:    If noErr is returned, you can assume a valid pict.
  642.  
  643.     Special Notes:    xxx put other comments here xxx
  644.  
  645. */
  646.  
  647. OSErr LoadPict(FSSpec *theFSSpec, PicHandle *pict, Handle *thumbnail,
  648.                     ThumbnailHeader *thumbnailHeader, CmPictureInfo *pictureInfo)
  649. {
  650.     OSErr                    err;
  651.     short                    myRefNum;
  652.     long                    thumbnailOffset;
  653.     long                    fileSize;
  654.     
  655.     //    Initialize variables used in this function.
  656.     myRefNum = -1;
  657.     err = noErr;
  658.     if ( pict != nil )
  659.         *pict = nil;
  660.     if ( thumbnail != nil )
  661.         *thumbnail = nil;
  662.     if ( thumbnailHeader != nil ) {
  663.         thumbnailHeader->signature = 0;
  664.         thumbnailHeader->version = 0;
  665.         thumbnailHeader->flags = 0;
  666.         thumbnailHeader->dataSize = 0;
  667.     }
  668.     if ( pictureInfo != nil ) {
  669.         pictureInfo->pictureNo = 0;
  670.         pictureInfo->imageDataSize = 0;
  671.         pictureInfo->width = 0;
  672.         pictureInfo->height = 0;
  673.         (pictureInfo->dateAndTime).month = 0;
  674.         (pictureInfo->dateAndTime).day = 0;
  675.         (pictureInfo->dateAndTime).year = 0;
  676.         (pictureInfo->dateAndTime).hour = 0;
  677.         (pictureInfo->dateAndTime).minute = 0;
  678.         (pictureInfo->dateAndTime).second = 0;
  679.         pictureInfo->flashMode = 0;
  680.         pictureInfo->exposureTime = 0;
  681.         pictureInfo->FNumber = 0;
  682.         pictureInfo->pictureMode = 0;
  683.         pictureInfo->dataCompressionMode = 0;
  684.         pictureInfo->defectiveFlag = 0;
  685.     }
  686.  
  687.     //    Check parameters after initialization.
  688.     if ( theFSSpec == nil ) {
  689.         err = paramErr;
  690.         goto bail;
  691.     }
  692.     
  693.     //    Try data fork first.  The data fork must be greater than 512 in size...
  694.     err = FSpOpenDF(theFSSpec, fsRdPerm, &myRefNum);
  695.     if ( err != noErr ) {
  696.         myRefNum = -1;
  697.         err = noErr;    //    Remove err and try resource fork.
  698.         goto tryResourceFork;
  699.     }
  700.     err = GetEOF(myRefNum, &fileSize);
  701.     if ( err != noErr ) {
  702.         err = noErr;    //    Remove err and try resource fork.
  703.         goto tryResourceFork;
  704.     }
  705.     if ( fileSize > 512 ) {
  706.         long            headerSize, pictSize, origPictSize;
  707.         unsigned char    header[512];
  708.         
  709.         //    Read in fileHeader first.
  710.         headerSize = 512;
  711.         err = FSRead(myRefNum, &headerSize, header);
  712.         if ( err != noErr )
  713.             goto bail;
  714.         if ( headerSize != 512 ) {
  715.             err = ioErr;
  716.             goto bail;
  717.         }
  718.         
  719.         //    If it is a valid Venus or Nimbus file header, then we will use thumbnailOffset from
  720.         //    header.  We will also read in the CmPictureInfo in this case.  Otherwise, don't since
  721.         //    we can't be sure of the file version and structure.
  722.         //    We check the version to make sure it is 0 since that is the file format version
  723.         //    as defined in the "QuickTake File Format Specification for Venus/Nimbus".
  724.         if ( (((PictFileHeader *) header)->signature == 'qktk' &&
  725.                     ((PictFileHeader *) header)->version == 0) ||
  726.                 (((PictFileHeader *) header)->signature == 'qktn' &&
  727.                     ((PictFileHeader *) header)->version == 0) ) {
  728.             thumbnailOffset = ((PictFileHeader *) header)->thumbnailOffset;
  729.             *pictureInfo = *((CmPictureInfoPtr) (header + sizeof(PictFileHeader)));
  730.         } else
  731.             thumbnailOffset = 0;
  732.         
  733.         //    Read in pict.  If the thumbnail exists, then read upto the thumbnail.  Otherwise,
  734.         //    assume that the entire rest of file is part of picture.
  735.         if ( thumbnailOffset > 0 )
  736.             pictSize = thumbnailOffset - 512;
  737.         else
  738.             pictSize = fileSize - 512;
  739.         origPictSize = pictSize;
  740.         
  741.         //    Read in pict if requested.
  742.         if ( pict != nil ) {
  743.             *pict = (PicHandle) NewHandle(pictSize);
  744.             if ( *pict == nil )
  745.                 goto bail;
  746.             MoveHHi((Handle) *pict);
  747.             HLock((Handle) *pict);
  748.             err = FSRead(myRefNum, &pictSize, **pict);
  749.             if ( err != noErr )
  750.                 goto bail;
  751.             if ( pictSize != origPictSize) {
  752.                 err = ioErr;
  753.                 goto bail;
  754.             }
  755.             HUnlock((Handle) *pict);
  756.         } else {
  757.             //    Simply advance the file position otherwise.
  758.             err = SetFPos(myRefNum, fsFromMark, pictSize);
  759.             if ( err != noErr )
  760.                 goto bail;
  761.         }
  762.         
  763.         //    If there is a thumbnail, then continue.
  764.         if ( thumbnailOffset > 0 ) {
  765.             long                    readSize, origReadSize;
  766.             ThumbnailHeader            tempThumbnailHeader;
  767.             
  768.             //    Read in thumbnail header into tempThumbnailHeader.
  769.             readSize = sizeof(ThumbnailHeader);
  770.             origReadSize = readSize;
  771.             err = FSRead(myRefNum, &readSize, &tempThumbnailHeader);
  772.             if ( err != noErr )
  773.                 goto bail;
  774.             if ( readSize != origReadSize ) {
  775.                 err = ioErr;
  776.                 goto bail;
  777.             }
  778.  
  779.             //    Copy tempThumbnailHeader into thumbnailHeader if requested.
  780.             if ( thumbnailHeader != nil ) {
  781.                 *thumbnailHeader = tempThumbnailHeader;
  782.             }
  783.         
  784.             //    Now read in thumbnail if requested.
  785.             readSize = tempThumbnailHeader.dataSize;
  786.             origReadSize = readSize;
  787.             if ( thumbnail != nil ) {
  788.                 *thumbnail = NewHandle(readSize);
  789.                 if ( *thumbnail == nil )
  790.                     goto bail;
  791.                 MoveHHi(*thumbnail);
  792.                 HLock(*thumbnail);
  793.                 err = FSRead(myRefNum, &readSize, **thumbnail);
  794.                 if ( err != noErr )
  795.                     goto bail;
  796.                 if ( readSize != origReadSize ) {
  797.                     err = ioErr;
  798.                     goto bail;
  799.                 }
  800.                     
  801.                 HUnlock(*thumbnail);
  802.             }
  803.         }
  804.     }
  805.  
  806.     //    Try resource fork if we still haven't loaded a picture.
  807. tryResourceFork:
  808.     //    Close data fork first.
  809.     if ( myRefNum != -1 ) {
  810.         FSClose(myRefNum);
  811.         myRefNum = -1;
  812.     }
  813.     if ( *pict == nil ) {
  814.         short    resFile;
  815.         resFile = FSpOpenResFile(theFSSpec, fsRdPerm);
  816.         if ( resFile == -1 ) {
  817.             err = ioErr;
  818.             goto bail;
  819.         }
  820.         *pict = (PicHandle) Get1IndResource('PICT', 1);
  821.         if ( *pict != nil ) {
  822.             DetachResource((Handle) *pict);
  823.             HUnlock((Handle) *pict);
  824.         }
  825.         CloseResFile(resFile);
  826.     }
  827.     
  828. bail:
  829.     //    Close data fork if still opened.
  830.     if ( myRefNum != -1 )
  831.         FSClose(myRefNum);
  832.     
  833.     //    Dispose if error occured.
  834.     if ( err != noErr ) {
  835.         if ( pict != nil ) {
  836.             if ( *pict != nil ) {
  837.                 DisposeHandle((Handle) *pict);
  838.                 *pict = nil;
  839.             }
  840.         }
  841.         if ( thumbnail != nil ) {
  842.             if ( *thumbnail != nil ) {
  843.                 DisposeHandle((Handle) *thumbnail);
  844.                 *thumbnail = nil;
  845.             }
  846.         }
  847.     }
  848.     
  849.     return ( noErr );
  850. }
  851.  
  852. /* ------------------------------------------------------------------------- */
  853.  
  854. /*
  855.     Description:    SavePict()
  856.                     Given a FSSpec, save a QuickTake picture out!  The file will contain a pict.  SavePict() will try to
  857.                     create a proper fileHeader for the Pict.  If the pict is not a Venus or Nimbus compressed picture,
  858.                     then the thumbnail and thumbnailHeader is ignored.  A thumbnailHeader is required if thumbnail is passed in.
  859.  
  860.     Format Params:    
  861.         Name            Usage    Description/Assumptions
  862.         ----            ----    -----------------------
  863.         theFSSpec        PI        Pass in a valid FSSpec to load the picture from.
  864.         creatorType        PI        Creator Type for the file.
  865.         pict            PI        Pass in a pointer to a PicHandle.  If pointer is nil, then
  866.                                 a paramErr will be returned.  A valid PicHandle will be returned if
  867.                                 no error occured.
  868.         thumbnail        PI        If thumbnail is not nil, then a thumbnail will be saved.
  869.                                 thumbnailHeader must be valid.
  870.         thumbnailHeader    PI        If thumbnailHeader is not nil then it will be used if thumbnail
  871.                                 is valid.
  872.         pictureInfo        PI        If the pictureInfo is not nil, then it will be used.
  873.                                 
  874.     Usage: P=Parameter,R=ReturnValue,E=External,G=FileGlobal,L=Local,I=Input,O=Output
  875.     
  876.     Error Handling:    If noErr is returned, you can assume a valid pict file has been saved.
  877.  
  878.     Special Notes:    xxx put other comments here xxx
  879.  
  880. */
  881.  
  882. OSErr SavePict(FSSpec *theFSSpec, OSType creatorType, PicHandle pict, Handle thumbnail,
  883.                     ThumbnailHeader *thumbnailHeader, CmPictureInfo *pictureInfo)
  884. {
  885.     OSErr                    err;
  886.     short                    myRefNum;
  887.     short                    myResRefNum;
  888.     PictFileHeader            fileHeader;
  889.     unsigned char            header[512];
  890.     long                    writeSize;
  891.     long                    i;
  892.     char                    state;
  893.     char                    icnmask_vert[128] = { 
  894.                                 15, 255, 255, 240, 15, 255, 255, 240, 15, 255, 255, 240, 15, 255, 255, 240,
  895.                                 15, 255, 255, 240, 15, 255, 255, 240, 15, 255, 255, 240, 15, 255, 255, 240,
  896.                                 15, 255, 255, 240, 15, 255, 255, 240, 15, 255, 255, 240, 15, 255, 255, 240,
  897.                                 15, 255, 255, 240, 15, 255, 255, 240, 15, 255, 255, 240, 15, 255, 255, 240,
  898.                                 15, 255, 255, 240, 15, 255, 255, 240, 15, 255, 255, 240, 15, 255, 255, 240,
  899.                                 15, 255, 255, 240, 15, 255, 255, 240, 15, 255, 255, 240, 15, 255, 255, 240,
  900.                                 15, 255, 255, 240, 15, 255, 255, 240, 15, 255, 255, 240, 15, 255, 255, 240,
  901.                                 15, 255, 255, 240, 15, 255, 255, 240, 15, 255, 255, 240, 15, 255, 255, 240};
  902.     char                    icnmask_horiz[128] = {
  903.                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  904.                                 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  905.                                 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  906.                                 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  907.                                 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  908.                                 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  909.                                 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  910.                                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  911.     
  912.     //    Initialize for getting pict.
  913.     myRefNum = -1;
  914.     myResRefNum = -1;
  915.     err = noErr;
  916.     
  917.     //    Check for parameter errors.
  918.     if ( pict == nil || theFSSpec == nil ) {
  919.         err = paramErr;
  920.         goto bail;
  921.     }
  922.     if ( thumbnail != nil ) {
  923.         if ( thumbnailHeader == nil ) {
  924.             err = paramErr;
  925.             goto bail;
  926.         }
  927.     }
  928.     
  929.     //    Initialize variables used.
  930.     for ( i=0; i<512; i++ ) {
  931.         header[i] = 0;
  932.     }
  933.     err = GetFileHeaderFromPict(pict, &fileHeader);
  934.     if ( err != noErr ) {
  935.         fileHeader.signature = 0;
  936.         fileHeader.version = 0;
  937.         fileHeader.flags = 0;
  938.         fileHeader.thumbnailOffset = 0;
  939.     }
  940.     
  941.     //    Create file.
  942.     err = FSpCreate(theFSSpec, creatorType, 'PICT', smSystemScript);
  943.     if ( err != noErr) {
  944.         //    If file already exists, then delete it and try again.
  945.         if ( err == dupFNErr ) {
  946.             err = FSpDelete(theFSSpec);
  947.             if ( err != noErr )
  948.                 goto bail;
  949.             err = FSpCreate(theFSSpec, creatorType, 'PICT', smSystemScript);
  950.             if ( err != noErr )
  951.                 goto bail;
  952.         } else
  953.             goto bail;
  954.     }
  955.     
  956.     //    Write data fork.
  957.     err = FSpOpenDF(theFSSpec, fsWrPerm, &myRefNum);
  958.     if ( err != noErr ) {
  959.         myRefNum = -1;
  960.         goto bail;
  961.     }
  962.     
  963.     //    Create and write a fileheader.  If we aren't writing thumbnail, then for thumbnailOffset to zero.
  964.     writeSize = 512;
  965.     ((PictFileHeader *) header)->signature = fileHeader.signature;
  966.     ((PictFileHeader *) header)->version = fileHeader.version;
  967.     ((PictFileHeader *) header)->flags = fileHeader.flags;
  968.     if ( thumbnail != nil )
  969.         ((PictFileHeader *) header)->thumbnailOffset = fileHeader.thumbnailOffset;
  970.     else
  971.         ((PictFileHeader *) header)->thumbnailOffset = 0;
  972.     if ( pictureInfo != nil )
  973.         *((CmPictureInfoPtr) (header + sizeof(PictFileHeader))) = *pictureInfo;
  974.     err = FSWrite(myRefNum, &writeSize, header);
  975.     if ( err != noErr )
  976.         goto bail;
  977.     if ( writeSize != 512 ) {
  978.         err = ioErr;
  979.         goto bail;
  980.     }
  981.     
  982.     //    Write the pict.
  983.     writeSize = GetHandleSize((Handle) pict);
  984.     state = HGetState((Handle) pict);
  985.     HLock((Handle) pict);
  986.     err = FSWrite(myRefNum, &writeSize, *pict);
  987.     HSetState((Handle)pict, state);
  988.     if ( err != noErr )
  989.         goto bail;
  990.     if ( writeSize != GetHandleSize((Handle) pict)) {
  991.         err = ioErr;
  992.         goto bail;
  993.     }
  994.  
  995.     //    Write the thumbnail header and thumbnail if we are writing out thumbnail.
  996.     if ( (thumbnail != nil) && (fileHeader.thumbnailOffset > 0)) {
  997.         //    Write the thumbnail header.
  998.         writeSize = sizeof(ImageHeader);
  999.         err = FSWrite(myRefNum, &writeSize, thumbnailHeader);
  1000.         if ( err != noErr )
  1001.             goto bail;
  1002.         if ( writeSize != sizeof(ImageHeader)) {
  1003.             err = ioErr;
  1004.             goto bail;
  1005.         }
  1006.     
  1007.         //    Write the thumbnail.
  1008.         writeSize = GetHandleSize(thumbnail);
  1009.         state = HGetState(thumbnail);
  1010.         HLock(thumbnail);
  1011.         err = FSWrite(myRefNum, &writeSize, *thumbnail);
  1012.         HSetState(thumbnail, state);
  1013.         if ( err != noErr )
  1014.             goto bail;
  1015.         if ( writeSize != GetHandleSize(thumbnail)) {
  1016.             err = ioErr;
  1017.             goto bail;
  1018.         }
  1019.     }
  1020.     
  1021.     //    Close data fork.
  1022.     err = FSClose(myRefNum);
  1023.     myRefNum = -1;
  1024.     if ( err != noErr ) {
  1025.         goto bail;
  1026.     }
  1027.     
  1028.     //    If we have, then also create custom icons.
  1029.     if ( (thumbnail != nil) ) {
  1030.         GWorldPtr    myGWorld;
  1031.         PicHandle    myPict;
  1032.         Rect        iconRect, boundsRect = {0, 0, 32, 32};
  1033.         Handle        icl8, icl4, icn;
  1034.  
  1035.         //    Determine orientation.
  1036.         if ( thumbnailHeader->flags & kQktkVerticalImage )
  1037.             SetRect(&iconRect, 4, 0, 28, 32);
  1038.         else
  1039.             SetRect(&iconRect, 0, 4, 32, 28);
  1040.         
  1041.         //    Create resource fork.
  1042.         FSpCreateResFile(theFSSpec, creatorType, 'PICT', smSystemScript);
  1043.         err = ResError();
  1044.         if ( err != noErr )
  1045.             goto bail;
  1046.         
  1047.         //    Write resource fork.
  1048.         myResRefNum = FSpOpenResFile(theFSSpec, fsRdWrPerm);
  1049.         if ( myResRefNum == -1 ) {
  1050.             err = ioErr;
  1051.             goto bail;
  1052.         }
  1053.         
  1054.         //    Create temporary picture.
  1055.         state = HGetState(thumbnail);
  1056.         HLock(thumbnail);
  1057.         err = MakeQuickTakePicture((ImageHeader *) thumbnailHeader, *thumbnail, nil, nil, &myPict);
  1058.         HSetState(thumbnail, state);
  1059.         if ( err != noErr )
  1060.             goto bail;
  1061.         
  1062.         //    Create new handles needed.
  1063.         icl8 = NewHandle(1024);
  1064.         if ( icl8 == nil ) {
  1065.             DisposeHandle((Handle) myPict);
  1066.             goto bail;
  1067.         }
  1068.         MoveHHi(icl8);
  1069.         HLock(icl8);
  1070.         icl4 = NewHandle(512);
  1071.         if ( icl4 == nil ) {
  1072.             DisposeHandle((Handle) myPict);
  1073.             DisposeHandle(icl8);
  1074.             err = memFullErr;
  1075.             goto bail;
  1076.         }
  1077.         MoveHHi(icl4);
  1078.         HLock(icl4);
  1079.         icn = NewHandle(256);
  1080.         if ( icn == nil ) {
  1081.             DisposeHandle((Handle) myPict);
  1082.             DisposeHandle(icl8);
  1083.             DisposeHandle(icl4);
  1084.             err = memFullErr;
  1085.             goto bail;
  1086.         }
  1087.         MoveHHi(icn);
  1088.         HLock(icn);
  1089.         
  1090.         //    Draw picture into temporary 8 bit gworld
  1091.         err = NewGWorld(&myGWorld, 8, &boundsRect, nil, nil, 0);
  1092.         if ( err == noErr ) {
  1093.             CGrafPtr            saveport;
  1094.             GDHandle            savegdevice;
  1095.             short                rowBytes;
  1096.             Ptr                    from;
  1097.             
  1098.             GetGWorld(&saveport, &savegdevice);
  1099.             SetGWorld(myGWorld, nil);
  1100.             LockPixels(GetGWorldPixMap(myGWorld));
  1101.             EraseRect(&boundsRect);
  1102.             HLock((Handle) myPict);
  1103.             DrawPicture(myPict, &iconRect);
  1104.             HUnlock((Handle) myPict);
  1105.             rowBytes = (**(myGWorld->portPixMap)).rowBytes & 0x3FFF;
  1106.             from = (**(myGWorld->portPixMap)).baseAddr;
  1107.             for (i=0; i<32; i++ ) {
  1108.                 BlockMove(from + (rowBytes * i) , (*icl8) + (32 * i), 32);
  1109.             }
  1110.             UnlockPixels(GetGWorldPixMap(myGWorld));
  1111.             //    Put into file.
  1112.             AddResource(icl8, 'icl8', -16455, "\pCustom Icon");
  1113.             SetGWorld(saveport, savegdevice);
  1114.             DisposeGWorld(myGWorld);
  1115.             myGWorld = nil;
  1116.         } else {
  1117.             DisposeHandle(icl8);
  1118.         }
  1119.         
  1120.         //    Draw picture into temporary 4 bit gworld
  1121.         err = NewGWorld(&myGWorld, 4, &boundsRect, nil, nil, 0);
  1122.         if ( err == noErr ) {
  1123.             CGrafPtr            saveport;
  1124.             GDHandle            savegdevice;
  1125.             short                rowBytes;
  1126.             Ptr                    from;
  1127.             
  1128.             GetGWorld(&saveport, &savegdevice);
  1129.             SetGWorld(myGWorld, nil);
  1130.             LockPixels(GetGWorldPixMap(myGWorld));
  1131.             EraseRect(&boundsRect);
  1132.             HLock((Handle) myPict);
  1133.             DrawPicture(myPict, &iconRect);
  1134.             HUnlock((Handle) myPict);
  1135.             rowBytes = (**(myGWorld->portPixMap)).rowBytes & 0x3FFF;
  1136.             from = (**(myGWorld->portPixMap)).baseAddr;
  1137.             for (i=0; i<32; i++ ) {
  1138.                 BlockMove(from + (rowBytes * i) , (*icl4) + (16 * i), 16);
  1139.             }
  1140.             UnlockPixels(GetGWorldPixMap(myGWorld));
  1141.             //    Put into file.
  1142.             AddResource(icl4, 'icl4', -16455, "\pCustom Icon");
  1143.             SetGWorld(saveport, savegdevice);
  1144.             DisposeGWorld(myGWorld);
  1145.             myGWorld = nil;
  1146.         } else {
  1147.             DisposeHandle(icl4);
  1148.         }
  1149.         
  1150.         //    Draw picture into temporary 1 bit gworld
  1151.         err = NewGWorld(&myGWorld, 1, &boundsRect, nil, nil, 0);
  1152.         if ( err == noErr ) {
  1153.             CGrafPtr            saveport;
  1154.             GDHandle            savegdevice;
  1155.             short                rowBytes;
  1156.             Ptr                    from;
  1157.             
  1158.             GetGWorld(&saveport, &savegdevice);
  1159.             SetGWorld(myGWorld, nil);
  1160.             LockPixels(GetGWorldPixMap(myGWorld));
  1161.             EraseRect(&boundsRect);
  1162.             HLock((Handle) myPict);
  1163.             DrawPicture(myPict, &iconRect);
  1164.             HUnlock((Handle) myPict);
  1165.             rowBytes = (**(myGWorld->portPixMap)).rowBytes & 0x3FFF;
  1166.             from = (**(myGWorld->portPixMap)).baseAddr;
  1167.             for (i=0; i<32; i++ ) {
  1168.                 BlockMove(from + (rowBytes*i) , (*icn) + (4*i), 4);
  1169.             }
  1170.             if ( thumbnailHeader->flags & kQktkVerticalImage )
  1171.                 BlockMove(icnmask_vert , (*icn) + 128, 128);
  1172.             else
  1173.                 BlockMove(icnmask_horiz , (*icn) + 128, 128);
  1174.             UnlockPixels(GetGWorldPixMap(myGWorld));
  1175.             //    Put into file.
  1176.             AddResource(icn, 'ICN#', -16455, "\pCustom Icon");
  1177.             SetGWorld(saveport, savegdevice);
  1178.             DisposeGWorld(myGWorld);
  1179.             myGWorld = nil;
  1180.         } else {
  1181.             DisposeHandle(icn);
  1182.         }
  1183.         
  1184.         //    Dispose temporary picture.
  1185.         DisposeHandle((Handle) myPict);
  1186.         
  1187.         //    Close resource fork.
  1188.         CloseResFile(myResRefNum);
  1189.         myResRefNum = -1;
  1190.         err = ResError();
  1191.         if ( err != noErr ) {
  1192.             goto bail;
  1193.         }
  1194.         
  1195.         //    Set custom icon info.
  1196.         err = FSpSetHasCustomIcon(theFSSpec);
  1197.         if ( err != noErr )
  1198.             goto bail;
  1199.     }
  1200.     
  1201.     //    Done.
  1202.     err = noErr;
  1203.  
  1204. bail:
  1205.     if ( myRefNum != -1 )
  1206.         FSClose(myRefNum);
  1207.     if ( myResRefNum != -1 )
  1208.         CloseResFile(myResRefNum);
  1209.         
  1210.     return ( err );
  1211. }
  1212.  
  1213. /* ------------------------------------------------------------------------- */
  1214.  
  1215. /*
  1216.     Description:    GetFileHeaderFromPict()
  1217.                     Given a pict, return a proper pict file header if available!
  1218.  
  1219.     Format Params:    
  1220.         Name            Usage    Description/Assumptions
  1221.         ----            ----    -----------------------
  1222.         pict            PI        Pass in a PicHandle.
  1223.         fileHeader        PO        A fileHeader will be returned that follows the "QuickTake File Format
  1224.                                 Specifications for Venus/Nimbus" specs.  The thumbnail offset will be 0.
  1225.                                 
  1226.     Usage: P=Parameter,R=ReturnValue,E=External,G=FileGlobal,L=Local,I=Input,O=Output
  1227.     
  1228.     Error Handling:    If noErr is returned, you can assume a valid fileHeader has been returned.
  1229.  
  1230.     Special Notes:    xxx put other comments here xxx
  1231.  
  1232. */
  1233.  
  1234. pascal void MyStdPixForImageHeader(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask,
  1235.                         PixMap *matte, Rect *matteRect, short flags);
  1236. pascal void MyStdPixForImageHeader(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask,
  1237.                         PixMap *matte, Rect *matteRect, short flags)
  1238. {
  1239.     OSErr                    err;
  1240.     Ptr                        data;
  1241.     ImageHeader                imageHeader;
  1242.     
  1243.     err = GetCompressedPixMapInfo(src, nil, &data, nil, nil, nil);
  1244.     if ( err == noErr ) {
  1245.         imageHeader = *((ImageHeader *) data);
  1246.         if ( (imageHeader.signature == 'qktk' && imageHeader.version == 1)
  1247.                 || (imageHeader.signature == 'qktn' && imageHeader.version == 2) ) {
  1248.             gImageHeader = imageHeader;
  1249.         }
  1250.     }
  1251. }
  1252.  
  1253. OSErr GetFileHeaderFromPict(PicHandle pict, PictFileHeader *fileHeader)
  1254. {
  1255.     OSErr                    err;
  1256.     CGrafPtr                saveport;
  1257.     GDHandle                savegdevice;
  1258.     GWorldPtr                myGWorld;
  1259.     Rect                    boundsRect = {0, 0, 8, 8};
  1260.     CQDProcs                bottlenecks;
  1261.     UniversalProcPtr        myProc;
  1262.     char                    state;
  1263.     
  1264.     //    Things that we must initialize first.
  1265.     GetGWorld(&saveport, &savegdevice);
  1266.     myGWorld = nil;
  1267.     gImageHeader.signature = 'none';
  1268.     gImageHeader.version = -1;
  1269.     gImageHeader.flags = 0;
  1270.     gImageHeader.dataSize = 0;
  1271.     
  1272.     if ( pict == nil ) {
  1273.         err = paramErr;
  1274.         goto bail;
  1275.     }
  1276.     if ( fileHeader == nil ) {
  1277.         err = paramErr;
  1278.         goto bail;
  1279.     }
  1280.     
  1281.     //    Rather than depend on a graphics port, we create an offscreen gworld to use as the current
  1282.     //    port and gdevice for creating the picture.
  1283.     err = NewGWorld(&myGWorld, 32, &boundsRect, nil, nil, 0);
  1284.     if ( err != noErr ) {
  1285.         myGWorld = nil;
  1286.         goto bail;
  1287.     }
  1288.     if ( myGWorld == nil ) {
  1289.         err = memFullErr;
  1290.         myGWorld = nil;
  1291.         goto bail;
  1292.     }
  1293.     SetGWorld(myGWorld, nil);
  1294.     LockPixels(GetGWorldPixMap(myGWorld));
  1295.     
  1296.     //    If the gworld was created properly, then create fileHeader.
  1297.     SetStdCProcs(&bottlenecks);
  1298.     myProc = bottlenecks.newProc1 = (UniversalProcPtr) NewStdPixProc(MyStdPixForImageHeader);
  1299.     (*myGWorld).grafProcs = &bottlenecks;
  1300.     state = HGetState((Handle) pict);
  1301.     HLock((Handle) pict);
  1302.     DrawPicture(pict, &((**pict).picFrame));
  1303.     HSetState((Handle) pict, state);
  1304.     UnlockPixels(GetGWorldPixMap(myGWorld));
  1305.     DisposeRoutineDescriptor(myProc);
  1306.     
  1307.     //    Copy it in from the global variable.
  1308.     if ( gImageHeader.signature == 'none' && gImageHeader.version == -1 ) {
  1309.         err = -1;
  1310.         goto bail;
  1311.     } else {
  1312.         (*fileHeader).signature = gImageHeader.signature;
  1313.         (*fileHeader).version = 0;
  1314.         (*fileHeader).flags = gImageHeader.flags & (kQktkStdResImage | kQktkHiResImage);
  1315.         (*fileHeader).thumbnailOffset = 512 + GetHandleSize((Handle) pict);
  1316.     }
  1317.     
  1318. bail:
  1319.     SetGWorld(saveport, savegdevice);
  1320.     
  1321.     if ( myGWorld != nil )
  1322.         DisposeGWorld(myGWorld);
  1323.         
  1324.     return (err);
  1325. }
  1326.  
  1327. /* ------------------------------------------------------------------------- */
  1328.  
  1329. /*
  1330.     Description:    GetImageHeaderFromPict()
  1331.                     Given a pict, return a proper image header if available!
  1332.  
  1333.     Format Params:    
  1334.         Name            Usage    Description/Assumptions
  1335.         ----            ----    -----------------------
  1336.         pict            PI        Pass in a PicHandle.
  1337.         imageHeader        PO        An imageHeader will be returned that follows the "QuickTake File Format
  1338.                                 Specifications for Venus/Nimbus" specs.
  1339.                                 
  1340.     Usage: P=Parameter,R=ReturnValue,E=External,G=FileGlobal,L=Local,I=Input,O=Output
  1341.     
  1342.     Error Handling:    If noErr is returned, you can assume a valid fileHeader has been returned.
  1343.  
  1344.     Special Notes:    xxx put other comments here xxx
  1345.  
  1346. */
  1347.  
  1348. OSErr GetImageHeaderFromPict(PicHandle pict, ImageHeader *imageHeader)
  1349. {
  1350.     OSErr                    err;
  1351.     CGrafPtr                saveport;
  1352.     GDHandle                savegdevice;
  1353.     GWorldPtr                myGWorld;
  1354.     Rect                    boundsRect = {0, 0, 8, 8};
  1355.     CQDProcs                bottlenecks;
  1356.     UniversalProcPtr        myProc;
  1357.     char                    state;
  1358.  
  1359.     //    Things that we must initialize first.
  1360.     GetGWorld(&saveport, &savegdevice);
  1361.     myGWorld = nil;
  1362.     gImageHeader.signature = 'none';
  1363.     gImageHeader.version = -1;
  1364.     gImageHeader.flags = 0;
  1365.     gImageHeader.dataSize = 0;
  1366.     
  1367.     if ( pict == nil ) {
  1368.         err = paramErr;
  1369.         goto bail;
  1370.     }
  1371.     if ( imageHeader == nil ) {
  1372.         err = paramErr;
  1373.         goto bail;
  1374.     }
  1375.     
  1376.     //    Rather than depend on a graphics port, we create an offscreen gworld to use as the current
  1377.     //    port and gdevice for creating the picture.
  1378.     err = NewGWorld(&myGWorld, 32, &boundsRect, nil, nil, 0);
  1379.     if ( err != noErr ) {
  1380.         myGWorld = nil;
  1381.         goto bail;
  1382.     }
  1383.     if ( myGWorld == nil ) {
  1384.         err = memFullErr;
  1385.         myGWorld = nil;
  1386.         goto bail;
  1387.     }
  1388.     SetGWorld(myGWorld, nil);
  1389.     LockPixels(GetGWorldPixMap(myGWorld));
  1390.     
  1391.     //    If the gworld was created properly, then create fileHeader.
  1392.     SetStdCProcs(&bottlenecks);
  1393.     myProc = bottlenecks.newProc1 = (UniversalProcPtr) NewStdPixProc(MyStdPixForImageHeader);
  1394.     (*myGWorld).grafProcs = &bottlenecks;
  1395.     state = HGetState((Handle) pict);
  1396.     HLock((Handle) pict);
  1397.     DrawPicture(pict, &((**pict).picFrame));
  1398.     HSetState((Handle) pict, state);
  1399.     UnlockPixels(GetGWorldPixMap(myGWorld));
  1400.     DisposeRoutineDescriptor(myProc);
  1401.     
  1402.     //    Copy it in from the global variable.
  1403.     if ( gImageHeader.signature == 'none' && gImageHeader.version == -1 ) {
  1404.         err = -1;
  1405.         goto bail;
  1406.     } else {
  1407.         *imageHeader = gImageHeader;
  1408.     }
  1409.     
  1410. bail:
  1411.     SetGWorld(saveport, savegdevice);
  1412.     
  1413.     if ( myGWorld != nil )
  1414.         DisposeGWorld(myGWorld);
  1415.         
  1416.     return (err);
  1417. }
  1418.  
  1419. /* ------------------------------------------------------------------------- */
  1420.  
  1421. /*
  1422.     Description:    GetImageBufferFromPict()
  1423.                     Given a pict, return a proper image buffer if available!  The buffer returned
  1424.                     is a Ptr which must be disposed of by the caller.
  1425.  
  1426.     Format Params:    
  1427.         Name            Usage    Description/Assumptions
  1428.         ----            ----    -----------------------
  1429.         pict            PI        Pass in a PicHandle.
  1430.         imageBuffer        PO        A image bufer for a QuickTake pict will be returned.
  1431.                                 
  1432.     Usage: P=Parameter,R=ReturnValue,E=External,G=FileGlobal,L=Local,I=Input,O=Output
  1433.     
  1434.     Error Handling:    If noErr is returned, you can assume a valid fileHeader has been returned.
  1435.  
  1436.     Special Notes:    xxx put other comments here xxx
  1437.  
  1438. */
  1439.  
  1440. pascal void MyStdPixForImageBuffer(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask,
  1441.                         PixMap *matte, Rect *matteRect, short flags);
  1442. pascal void MyStdPixForImageBuffer(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask,
  1443.                         PixMap *matte, Rect *matteRect, short flags)
  1444. {
  1445.     OSErr                    err;
  1446.     Ptr                        data;
  1447.     ImageHeader                imageHeader;
  1448.     Ptr                        tempImageBuffer;
  1449.     
  1450.     err = GetCompressedPixMapInfo(src, nil, &data, nil, nil, nil);
  1451.     if ( err == noErr ) {
  1452.         imageHeader = *((ImageHeader *) data);
  1453.         if ( (imageHeader.signature == 'qktk' && imageHeader.version == 1)
  1454.                 || (imageHeader.signature == 'qktn' && imageHeader.version == 2) ) {
  1455.             //    Do only the first compressed picture.
  1456.             if ( gImageBuffer == nil ) {
  1457.                 tempImageBuffer = NewPtr(imageHeader.dataSize);
  1458.                 if ( tempImageBuffer != nil ) {
  1459.                     BlockMove(data + sizeof(ImageHeader), tempImageBuffer, imageHeader.dataSize);
  1460.                     gImageBuffer = tempImageBuffer;
  1461.                 }
  1462.             }
  1463.         }
  1464.     }
  1465. }
  1466.  
  1467. OSErr GetImageBufferFromPict(PicHandle pict, Ptr *imageBuffer)
  1468. {
  1469.     OSErr                    err;
  1470.     CGrafPtr                saveport;
  1471.     GDHandle                savegdevice;
  1472.     GWorldPtr                myGWorld;
  1473.     Rect                    boundsRect = {0, 0, 8, 8};
  1474.     CQDProcs                bottlenecks;
  1475.     UniversalProcPtr        myProc;
  1476.     char                    state;
  1477.  
  1478.     //    Things that we must initialize first.
  1479.     GetGWorld(&saveport, &savegdevice);
  1480.     myGWorld = nil;
  1481.     gImageBuffer = nil;
  1482.     
  1483.     if ( pict == nil ) {
  1484.         err = paramErr;
  1485.         goto bail;
  1486.     }
  1487.     if ( imageBuffer == nil ) {
  1488.         err = paramErr;
  1489.         goto bail;
  1490.     }
  1491.     
  1492.     //    Rather than depend on a graphics port, we create an offscreen gworld to use as the current
  1493.     //    port and gdevice for creating the picture.
  1494.     err = NewGWorld(&myGWorld, 32, &boundsRect, nil, nil, 0);
  1495.     if ( err != noErr ) {
  1496.         myGWorld = nil;
  1497.         goto bail;
  1498.     }
  1499.     if ( myGWorld == nil ) {
  1500.         err = memFullErr;
  1501.         myGWorld = nil;
  1502.         goto bail;
  1503.     }
  1504.     SetGWorld(myGWorld, nil);
  1505.     LockPixels(GetGWorldPixMap(myGWorld));
  1506.     
  1507.     //    If the gworld was created properly, then create fileHeader.
  1508.     SetStdCProcs(&bottlenecks);
  1509.     myProc = bottlenecks.newProc1 = (UniversalProcPtr) NewStdPixProc(MyStdPixForImageBuffer);
  1510.     (*myGWorld).grafProcs = &bottlenecks;
  1511.     state = HGetState((Handle) pict);
  1512.     HLock((Handle) pict);
  1513.     DrawPicture(pict, &((**pict).picFrame));
  1514.     HSetState((Handle) pict, state);
  1515.     UnlockPixels(GetGWorldPixMap(myGWorld));
  1516.     DisposeRoutineDescriptor(myProc);
  1517.     
  1518.     //    Copy it in from the global variable.
  1519.     *imageBuffer = gImageBuffer;
  1520.     if ( gImageBuffer == nil )
  1521.         err = -1;
  1522. bail:
  1523.     SetGWorld(saveport, savegdevice);
  1524.     
  1525.     if ( myGWorld != nil )
  1526.         DisposeGWorld(myGWorld);
  1527.         
  1528.     return (err);
  1529. }
  1530.  
  1531. /* ------------------------------------------------------------------------- */
  1532.  
  1533. /*
  1534.     Description:    DrawPictureWIthProgress()
  1535.                     Given a pict, draw it with a progress proc!
  1536.  
  1537.     Format Params:    
  1538.         Name            Usage    Description/Assumptions
  1539.         ----            ----    -----------------------
  1540.         pict            PI        Pass in a PicHandle.
  1541.         pictRect        PI        A fileHeader will be returned that follows the "QuickTake File Format
  1542.                                 Specifications for Venus/Nimbus" specs.  The thumbnail offset will be 0.
  1543.                                 
  1544.     Usage: P=Parameter,R=ReturnValue,E=External,G=FileGlobal,L=Local,I=Input,O=Output
  1545.     
  1546.     Error Handling:    none.
  1547.  
  1548.     Special Notes:    xxx put other comments here xxx
  1549.  
  1550. */
  1551.  
  1552. pascal void MyStdPixWithProgress(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask,
  1553.                         PixMap *matte, Rect *matteRect, short flags);
  1554. pascal void MyStdPixWithProgress(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask,
  1555.                         PixMap *matte, Rect *matteRect, short flags)
  1556. {
  1557.     OSErr                    err;
  1558.     ImageDescriptionHandle    desc;
  1559.     Ptr                        data;
  1560.     long                    bufferSize;
  1561.     ICMDataProcRecord        dataProc;
  1562.     ICMProgressProcRecord    progressProc;
  1563.     CGrafPtr                curPort;
  1564.     PixMapHandle            dst;
  1565.     
  1566.     err = GetCompressedPixMapInfo(src, &desc, &data, &bufferSize, &dataProc, &progressProc);
  1567.     GetPort((GrafPtr *) &curPort);
  1568.     dst = (*curPort).portPixMap;
  1569.     FDecompressImage(data, desc, dst, srcRect, matrix, mode, mask, &matte, matteRect, codecHighQuality,
  1570.                         anyCodec, bufferSize, nil, (ICMProgressProcRecordPtr) -1);
  1571. }
  1572.  
  1573. void DrawPictureWithProgress(PicHandle pict, Rect *pictRect)
  1574. {
  1575.     CQDProcs                bottlenecks, *oldbottlenecks;
  1576.     CGrafPtr                curPort;
  1577.     UniversalProcPtr        myProc;
  1578.     char                    state;
  1579.     
  1580.     if ( pict == nil ) {
  1581.         return;
  1582.     }
  1583.     
  1584.     SetStdCProcs(&bottlenecks);
  1585.     myProc = bottlenecks.newProc1 = (UniversalProcPtr) NewStdPixProc(MyStdPixWithProgress);
  1586.     GetPort((GrafPtr *) &curPort);
  1587.     oldbottlenecks = (*curPort).grafProcs;
  1588.     (*curPort).grafProcs = &bottlenecks;
  1589.     state = HGetState((Handle) pict);
  1590.     HLock((Handle) pict);
  1591.     DrawPicture(pict, pictRect);
  1592.     HSetState((Handle) pict, state);
  1593.     (*curPort).grafProcs = oldbottlenecks;
  1594.     DisposeRoutineDescriptor(myProc);
  1595.  
  1596. }
  1597.